<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Licensed ( https://opensource.org/licenses/MIT )
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// +----------------------------------------------------------------------
// | Redis 操作
// +----------------------------------------------------------------------
namespace Inphp\Core\Db;

use Inphp\Core\Db\Redis\Connection;

class Redis
{
    /**
     * 连接对象
     * @var Connection|null
     */
    private static Connection|null $connection = null;

    /**
     * 配置
     * @var array
     */
    private static array $config = [];

    /**
     * 初始化
     */
    public static function init(): void
    {
        if (!self::$connection) {
            $config = self::getConfig();
            self::$connection = new Connection($config);
        }
    }

    /**
     * 获取配置
     * @return array
     */
    public static function getConfig(): array
    {
        if (empty(self::$config)) {
            self::$config = Db::getConfig("redis");
        }
        return self::$config;
    }

    /**
     * 获取连接对象
     * @return Connection
     */
    public static function getConnection(): Connection
    {
        self::init();
        return self::$connection;
    }

    /**
     * 获取原始操作对象
     * @return \Redis
     */
    public static function getRedis(): \Redis
    {
        return self::getConnection()->get();
    }

    /**
     * 回收对象
     * @param \Redis $redis
     */
    public static function putRedis(\Redis $redis): void
    {
        self::getConnection()->put($redis);
    }

    /**
     * 获取名称前缀
     * @return string
     */
    public static function getNamePrefix(): string
    {
        return self::getConfig()['prefix'];
    }

    /**
     * 重新打包键名
     * @param string $name
     * @return string
     */
    public static function packName(string $name): string
    {
        return self::getNamePrefix().$name;
    }

    /**
     * 获取值
     * @param string $name
     * @param mixed|null $default
     * @param string|null $prefix
     * @return mixed
     */
    public static function get(string $name, mixed $default = null, ?string $prefix = null): mixed
    {
        //获取对象
        $redis = self::getRedis();
        //名称自动处理
        $name = !is_null($prefix) ? ($prefix.$name) : self::packName($name);
        //获取值
        $value = $redis->get($name) ?? $default;
        //自动转换
        $value = json_decode($value, true) ?? $value;
        //回收
        self::putRedis($redis);
        //返回值
        return $value;
    }

    /**
     * 保存值
     * @param string $name
     * @param mixed|null $value
     * @param int $expire
     * @param string|null $prefix
     */
    public static function set(string $name, mixed $value = null, int $expire = 0, ?string $prefix = null): void
    {
        if (is_null($value)) {
            //移除
            self::del($name, $prefix);
            return;
        }
        //获取对象
        $redis = self::getRedis();
        //名称自动处理
        $name = !is_null($prefix) ? ($prefix.$name) : self::packName($name);
        //值自动处理
        $value = is_array($value) || is_object($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value;
        //过期时间自动处理
        $expire = $expire == 0 ? self::getConfig()['expire'] : $expire;
        $expire = is_numeric($expire) && $expire >= -1 ? ceil($expire) : -1;
        if ($expire > 0) {
            $redis->setex($name, $expire, $value);
        } else {
            $redis->set($name, $value);
        }
        //保存已经记录的名称
        if (is_null($prefix)) {
            $key = self::packName('redis_tag_history_list');
            $list = $redis->get($key);
            $list = !empty($list) ? explode(",", $list) : [];
            if (!in_array($name, $list)) {
                $list[] = $name;
                $redis->set($key, join(",", $list));
            }
        }
        //回收
        self::putRedis($redis);
    }

    /**
     * 自增值
     * @param string $name
     * @return int
     */
    public static function incr(string $name, int $expire = 0, ?string $prefix = null): int
    {
        $id = self::get($name);
        $id = is_numeric($id) && $id >= 0 ? ceil($id) : null;
        if (is_null($id)) {
            self::set($name, 0, $expire);
            $id = 0;
        } else {
            $redis = self::getRedis();
            //名称自动处理
            $name = !is_null($prefix) ? ($prefix.$name) : self::packName($name);
            $redis->incr($name);
            $id += 1;
        }
        return (int) $id;
    }

    /**
     * 删除
     * @param string $name
     * @param string|null $prefix
     * @return bool
     */
    public static function del(string $name, ?string $prefix = null): bool
    {
        //获取对象
        $redis = self::getRedis();
        //名称自动处理
        $name = !is_null($prefix) ? ($prefix.$name) : self::packName($name);
        //
        if ($redis->del($name) > 0 && is_null($prefix)) {
            $key = self::packName('redis_tag_history_list');
            $list = $redis->get($key);
            $list = !empty($list) ? explode(",", $list) : [];
            $index = array_search($name, $list);
            if ($index !== false) {
                array_splice($list, $index, 1);
                if (empty($list)) {
                    $redis->del($key);
                } else {
                    $redis->set($key, join(",", $list));
                }
            }
        }
        //回收
        self::putRedis($redis);
        return true;
    }

    /**
     * 清除
     * @return int
     */
    public static function clean(): int
    {
        //获取对象
        $redis = self::getRedis();
        $key = self::packName('redis_tag_history_list');
        $list = $redis->get($key);
        $list = !empty($list) ? explode(",", $list) : [];
        $list[] = $key;
        $int = call_user_func_array([$redis, "del"], $list);
        //回收
        self::putRedis($redis);
        return $int;
    }
}